package com.dd.seckill.single.utils.redisdatainit;

import redis.clients.jedis.Jedis;

import java.sql.*;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

/**
 * @Author liuxianmeng
 * @CreateTime 2025/9/6 23:28
 * @Description 用户Token初始化 将模拟的用户token在系统启动前存入Redis
 */
public class UserTokenInitializer {
    // 数据库连接配置
    private static final String DB_URL = "jdbc:mysql://localhost:3306/dd_seckill?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
    private static final String DB_USERNAME = "root";
    private static final String DB_PASSWORD = "root";

    // Redis连接配置 TODO 使用时修改REDIS_HOST和REDIS_PASSWORD
    private static final String REDIS_HOST = "123456";
    private static final int REDIS_PORT = 21906;
    private static final String REDIS_PASSWORD = "123456"; // 如果没有密码，设为null

    // Redis键前缀
    public static final String REDIS_TOKEN_KEY_PREFIX = "seckill:user:token:";
    public static final String REDIS_USERID_KEY_PREFIX = "seckill:token:user:";

    // 字符集用于生成随机token
    private static final String CHAR_SET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    private static final int TOKEN_LENGTH = 16;

    public static void main(String[] args) {
        Connection dbConn = null;
        Jedis jedis = null;
        PrintWriter fileWriter = null;

        try {
            // 1. 建立数据库连接
            System.out.println("正在连接数据库...");
            dbConn = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);

            // 2. 建立Redis连接
            System.out.println("正在连接Redis...");
            jedis = new Jedis(REDIS_HOST, REDIS_PORT);
            if (REDIS_PASSWORD != null && !REDIS_PASSWORD.trim().isEmpty()) {
                jedis.auth(REDIS_PASSWORD);
            }

            // 3. 创建文件输出流
            System.out.println("创建token文件...");
            fileWriter = new PrintWriter(new FileWriter("user_token.txt", true)); // 追加模式

            // 4. 查询所有用户信息
            System.out.println("查询用户数据...");
            String querySql = "SELECT id, username FROM user";
            PreparedStatement pstmt = dbConn.prepareStatement(querySql);
            ResultSet rs = pstmt.executeQuery();

            // 5. 遍历用户信息并生成token
            System.out.println("开始生成token并写入Redis...");
            int count = 0;
            Random random = new Random();

            while (rs.next()) {
                long userId = rs.getLong("id");
                String username = rs.getString("username");

                // 生成随机16位token
                String token = generateRandomToken(random);

                // 写入Redis - 两种键存储方式方便查询
                // 方式1: user:token:{userId} -> token
                String userTokenKey = REDIS_TOKEN_KEY_PREFIX + userId;
                jedis.set(userTokenKey, token);

                // 方式2: token:user:{token} -> userId (方便通过token反查用户)
                String tokenUserKey = REDIS_USERID_KEY_PREFIX + token;
                jedis.set(tokenUserKey, String.valueOf(userId));

                // 写入文件: 用户ID,用户名,token
                fileWriter.println(userId + "," + username + "," + token);

                count++;
                if (count % 1000 == 0) {
                    System.out.println("已处理 " + count + " 个用户");
                }
            }

            System.out.println("Token初始化完成！共处理 " + count + " 个用户");

        } catch (SQLException e) {
            System.err.println("数据库操作失败: " + e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("文件操作失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (dbConn != null) dbConn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            if (jedis != null) jedis.close();

            if (fileWriter != null) fileWriter.close();
        }
    }

    /**
     * 生成随机16位token
     */
    private static String generateRandomToken(Random random) {
        StringBuilder tokenBuilder = new StringBuilder(TOKEN_LENGTH);
        for (int i = 0; i < TOKEN_LENGTH; i++) {
            int index = random.nextInt(CHAR_SET.length());
            tokenBuilder.append(CHAR_SET.charAt(index));
        }
        return tokenBuilder.toString();
    }
}
